package aaa.config;
/*
@Date:2025/6/18
*/

// 导入c3p0连接池相关类
import aaa.service.AccountServiceImpl;
import com.mchange.v2.c3p0.ComboPooledDataSource;
// 导入MyBatis相关类
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
// 导入Spring相关注解和类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
// 导入Spring事务相关类
import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
// 导入Java标准库类
import java.beans.PropertyVetoException;
import java.util.Properties;
import javax.sql.DataSource;

// 声明这是一个Spring配置类
@Configuration
public class DatabaseConfig {

    // 定义数据源Bean
    @Bean
    public DataSource dataSource() {
// 创建c3p0连接池实例
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        try {
// 设置MySQL 8.x JDBC驱动类
            dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
// 设置数据库连接URL，包含时区、字符集等参数
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/student?"
                    + "useSSL=false&"
                    + "characterEncoding=utf8&"
                    + "serverTimezone=Asia/Shanghai");
// 设置数据库用户名
            dataSource.setUser("root");
// 设置数据库密码
            dataSource.setPassword("123456");

// 配置连接池参数
            dataSource.setInitialPoolSize(5); // 初始连接数
            dataSource.setMinPoolSize(5); // 最小连接数
            dataSource.setMaxPoolSize(20); // 最大连接数
            dataSource.setAcquireIncrement(3); // 每次获取的连接数增量
            dataSource.setMaxIdleTime(300); // 最大空闲时间(秒)

        } catch (PropertyVetoException e) {
// 如果配置失败，抛出运行时异常
            throw new RuntimeException("数据库配置失败", e);
        }
        return dataSource;
    }

    // 定义MyBatis的SqlSessionFactory Bean
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 创建SqlSessionFactoryBean实例
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
// 设置数据源
        factory.setDataSource(dataSource);
// 设置MyBatis配置文件位置
        factory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
// 获取并返回SqlSessionFactory实例
        return factory.getObject();
    }

    // 定义Mapper扫描配置Bean
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
// 创建Mapper扫描配置器
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
// 设置Mapper接口所在的包路径
        configurer.setBasePackage("aaa.dao");
// 设置SqlSessionFactory的Bean名称
        configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return configurer;
    }

    // 定义JdbcTemplate Bean
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
// 创建并返回JdbcTemplate实例
        return new JdbcTemplate(dataSource);
    }

    // 定义事务管理器Bean
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
// 创建并返回基于数据源的事务管理器
        return new DataSourceTransactionManager(dataSource);
    }

    // 定义事务拦截器配置
    @Bean
    public TransactionInterceptor txAdvice(PlatformTransactionManager txManager) {
// 创建事务属性源，用于匹配方法名和事务属性
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

// 配置只读事务属性
        DefaultTransactionAttribute readOnlyTx = new DefaultTransactionAttribute();
        readOnlyTx.setReadOnly(true); // 设置为只读
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); // 传播行为

// 配置读写事务属性
        DefaultTransactionAttribute requiredTx = new DefaultTransactionAttribute();
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 传播行为
        requiredTx.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); // 隔离级别
        requiredTx.setTimeout(30); // 超时时间(秒)

// 将方法名模式与事务属性绑定
        source.addTransactionalMethod("find*", readOnlyTx); // 查询方法使用只读事务
        source.addTransactionalMethod("transfer*", requiredTx); // 转账方法使用读写事务
        source.addTransactionalMethod("save*", requiredTx); // 保存方法使用读写事务
        source.addTransactionalMethod("update*", requiredTx); // 更新方法使用读写事务
        source.addTransactionalMethod("delete*", requiredTx); // 删除方法使用读写事务

// 创建并返回事务拦截器
        return new TransactionInterceptor(txManager, source);
    }

    // 定义AOP自动代理创建器
    @Bean
    public BeanNameAutoProxyCreator autoProxyCreator() {
// 创建自动代理创建器
        BeanNameAutoProxyCreator proxy = new BeanNameAutoProxyCreator();
// 设置要代理的Bean名称模式(匹配Service实现类)
        proxy.setBeanNames("*ServiceImpl");
// 设置要应用的拦截器名称
        proxy.setInterceptorNames("txAdvice");
        return proxy;
    }




}
/**
 * 这个配置类主要完成了以下功能：
 *
 * 配置了c3p0数据库连接池
 * 集成了MyBatis框架
 * 配置了JdbcTemplate
 * 设置了声明式事务管理
 * 通过AOP实现了事务拦截
 * 每个Bean都通过Spring的@Bean注解进行声明，Spring容器启动时会自动创建这些Bean并管理它
 *
 */